#pragma once
#include <iostream>
#include <signal.h>
#include <functional>
#include "Sock.hpp"

class HttpServer
{
public:
    using func_t = std::function<void(int)>;

    // 构造函数
    HttpServer() {}

    HttpServer(const uint16_t &port, func_t func)
        : port_(port), func_(func)
    {
        // 创建套接字
        listensock_ = sock_.Socket();
        // 绑定
        sock_.Bind(listensock_, port_);
        // 监听
        sock_.Listen(listensock_);
    }

    // 析构
    ~HttpServer()
    {
        if (listensock_ > 0)
            close(listensock_);
    }

    // 启动服务端：接收连接客户端，派子进程处理业务
    void Start()
    {
        signal(SIGCHLD, SIG_IGN); // 子进程在终止时会自动清理，不会产生僵尸进程，也不会通知父进程。

        for (;;)
        {
            std::string clientip;
            uint16_t clientport;

            int servicesock = sock_.Accept(listensock_, &clientip, &clientport); // 输出型参数
            if (servicesock < 0)
                continue;    // 本次连接失败，重新连接
            if (fork() == 0) // 子进程:执行业务处理
            {
                close(listensock_); // 关闭无用套接字
                func_(servicesock); // 业务处理函数
                close(servicesock); // 完成后关闭套接字并退出进行
                exit(0);
            }
            close(servicesock); // 父进程也要关闭对其无用的套接字
        }
    }

private:
    int listensock_; // 监听套接字
    uint16_t port_;  // 端口号
    func_t func_;    // 业务处理函数
    Sock sock_;
};